{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c036d5f2",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 聪明办法学 Python 2nd Edition\n",
    "## Chapter 2 数据类型和操作 Data Types and Operators\n",
    "---\n",
    "聪明办法学 Python 教学团队\n",
    "\n",
    "<p>learn.python.the.smart.way@gmail.com</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "61cdefc8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T11:58:47.792314Z",
     "start_time": "2023-08-07T11:58:47.778799Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "import math\n",
    "def f():\n",
    "    return 42"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2ecc3af",
   "metadata": {
    "cell_style": "center",
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 常用内置类型 Builtin Types\n",
    "\n",
    ">我们提前导入了 `math` 库，并创建了一个函数 `f()` （内容并不重要）\n",
    "\n",
    "在本节中，我们将要见到这些基本类型：\n",
    "- 整数 Integer（int）\n",
    "- 浮点数 Float\n",
    "- 布尔值 Boolean（bool）\n",
    "- 类型 Type（是的，“类型”也是种类型！）\n",
    "\n",
    "严格的来说，Type 是一种 `类` 的 `对象`，Python 是一门“面向对象友好”的语言"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "2f810c66",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:13:41.171561Z",
     "start_time": "2023-08-07T12:13:41.152560Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'>\n"
     ]
    }
   ],
   "source": [
    "print(type(2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "89d47468",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:13:54.573538Z",
     "start_time": "2023-08-07T12:13:54.556538Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'float'>\n"
     ]
    }
   ],
   "source": [
    "print(type(2.2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "4e41979c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:14:36.954479Z",
     "start_time": "2023-08-07T12:14:36.948963Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'bool'>\n"
     ]
    }
   ],
   "source": [
    "print(type(2 < 2.2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ee6832c8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:15:44.271925Z",
     "start_time": "2023-08-07T12:15:44.264924Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'type'>\n"
     ]
    }
   ],
   "source": [
    "print(type(type(42)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2bf7020",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Python 中的一些基本类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "1474a64f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:16:14.285052Z",
     "start_time": "2023-08-07T12:16:14.278057Z"
    },
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'>\n",
      "<class 'float'>\n",
      "<class 'bool'>\n",
      "<class 'type'>\n"
     ]
    }
   ],
   "source": [
    "print(type(2))           # int\n",
    "print(type(2.2))         # float\n",
    "print(type(2 < 2.2))     # bool (boolean)\n",
    "print(type(type(42)))    # type "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17b1abe9",
   "metadata": {
    "cell_style": "center",
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "在今后的内容中，我们将会见到更多类型：\n",
    "- 字符串 String（str）\n",
    "- 列表 List\n",
    "- 元组 Tuple\n",
    "- 集合 Set\n",
    "- 字典 Dictionary（dict，或者你可以叫它 `映射 map`）\n",
    "- 复数 Complex Number（complex)\n",
    "- 函数 Function\n",
    "- 模块 Module\n",
    "\n",
    "`str`、`list`、`tuple`、`set`、`dict` 将尝试用 **`数组 Array`** 的方式讲授"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70464d81",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "后续课程中会见到的类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "967d8133",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:18:54.476664Z",
     "start_time": "2023-08-07T12:18:54.465663Z"
    },
    "cell_style": "center",
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'str'>\n",
      "<class 'list'>\n",
      "<class 'tuple'>\n",
      "<class 'set'>\n",
      "<class 'dict'>\n",
      "<class 'complex'>\n",
      "<class 'function'>\n",
      "<class 'module'>\n"
     ]
    }
   ],
   "source": [
    "print(type(\"2.2\"))       # str (string or text)\n",
    "print(type([1,2,3]))     # list\n",
    "print(type((1,2,3)))     # tuple\n",
    "print(type({1,2}))       # set\n",
    "print(type({1:42}))      # dict (dictionary or map)\n",
    "print(type(2+3j))        # complex  (complex number)\n",
    "print(type(f))           # function\n",
    "print(type(math))        # module"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bb6ed1c",
   "metadata": {
    "cell_style": "center",
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 常用内置常数 Builtin Constants\n",
    "\n",
    "`常数`区别于`变量`（将在下节课讲授），`常数`的值是固定的、不可改变的\n",
    "\n",
    "Python 内置了一些常量\n",
    "- True，用于表示 布尔 **`真`**\n",
    "- False，用于表示 布尔 **`假`**\n",
    "- None，代表 **`空`** ，用于空值\n",
    "\n",
    "`math` 库中的一些数学常量\n",
    "- pi，数学常数 $\\pi$ = 3.141592...，精确到可用精度\n",
    "- e，数学常数 $\\mathrm{e}$ = 2.718281...，精确到可用精度\n",
    "- tau，数学常数 $\\tau$ = 6.283185...，精确到可用精度（其实它不常用）\n",
    "- inf，浮点正无穷大，等价于 `float('inf')`，负无穷大使用 `-math.inf` "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "e178e8e9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:20:39.994917Z",
     "start_time": "2023-08-07T12:20:39.979404Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(True)\n",
    "print(False)\n",
    "print(None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "08eb2ca5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:20:45.664214Z",
     "start_time": "2023-08-07T12:20:45.658215Z"
    },
    "cell_style": "center",
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.141592653589793\n",
      "2.718281828459045\n",
      "6.283185307179586\n",
      "inf\n",
      "-inf\n"
     ]
    }
   ],
   "source": [
    "print(math.pi)\n",
    "print(math.e)\n",
    "print(math.tau)\n",
    "print(math.inf)\n",
    "print(-math.inf)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f058b597",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 常用内置运算符 Builtin Operators\n",
    "\n",
    "- 算术：`+`, `-`, `*`, `@`, `/`, `//`, `**`, `%`, `-` (一元算符), `+` (一元算符)\n",
    "- 关系：`<`, `<=`, `>=`, `>`, `==`, `!=`\n",
    "- 赋值： `+=`, `-=`, `*=`, `/=`, `//=`, `**=`, `%=`\n",
    "- 逻辑：`and`, `or`, `not`\n",
    "\n",
    "> 我们暂时跳过`按位运算符`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31fe070e",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 整除 Integer Division (//)\n",
    "\n",
    "> 这个知识点可能会在作业中发挥很大的作用，所以请多花些时间来理解它的运作方式\n",
    "\n",
    "`/` 指的是**浮点数**除法，它的结果是一个浮点数，例如 `2/1` 的结果是 `2.0`\n",
    "\n",
    "`//` 指的是**整除**除法，它的计算结果是整数，舍弃余数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aee8581d",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "`/` 是 **浮点数** 除法操作符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "076761a7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:31:27.875370Z",
     "start_time": "2023-08-07T12:31:27.858370Z"
    },
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 5/3  = 1.6666666666666667\n"
     ]
    }
   ],
   "source": [
    "print(\" 5/3  =\", (5/3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29102a25",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "`//` 代表 **整除**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "69cb4b9d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:31:57.647145Z",
     "start_time": "2023-08-07T12:31:57.634136Z"
    },
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 5//3 = 1\n",
      " 2//3 = 0\n",
      "-1//3 = -1\n",
      "-4//3 = -2\n"
     ]
    }
   ],
   "source": [
    "print(\" 5//3 =\", ( 5//3))\n",
    "print(\" 2//3 =\", ( 2//3))\n",
    "print(\"-1//3 =\", (-1//3))\n",
    "print(\"-4//3 =\", (-4//3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "523c1606",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 模运算或余数运算符 (%)\n",
    "\n",
    "> 这个知识点可能会在作业中发挥很大的作用，所以请多花些时间来理解它的运作方式\n",
    "\n",
    "`%` 代表模运算（取余），结果为商的余数\n",
    "\n",
    "例如：`5` 整除 `2` 的结果是 `2`，**余数**为 `1`，则 `5 % 2` 的结果为 `1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "d991607a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:37:43.498535Z",
     "start_time": "2023-08-07T12:37:43.478023Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 6%3 = 0\n",
      " 5%3 = 2\n",
      " 2%3 = 2\n",
      " 0%3 = 0\n",
      "-4%3 = 2\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "integer division or modulo by zero",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mZeroDivisionError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn [40], line 6\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m 0\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m3 =\u001b[39m\u001b[38;5;124m\"\u001b[39m, ( \u001b[38;5;241m0\u001b[39m\u001b[38;5;241m%\u001b[39m\u001b[38;5;241m3\u001b[39m))\n\u001b[0;32m      5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m-4\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m3 =\u001b[39m\u001b[38;5;124m\"\u001b[39m, (\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m4\u001b[39m\u001b[38;5;241m%\u001b[39m\u001b[38;5;241m3\u001b[39m))\n\u001b[1;32m----> 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m 3\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m0 =\u001b[39m\u001b[38;5;124m\"\u001b[39m, ( \u001b[38;5;241;43m3\u001b[39;49m\u001b[38;5;241;43m%\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m))\n",
      "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero"
     ]
    }
   ],
   "source": [
    "print(\" 6%3 =\", ( 6%3))\n",
    "print(\" 5%3 =\", ( 5%3))\n",
    "print(\" 2%3 =\", ( 2%3))\n",
    "print(\" 0%3 =\", ( 0%3))\n",
    "print(\"-4%3 =\", (-4%3))\n",
    "print(\" 3%0 =\", ( 3%0))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e48ce77",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "$ a \\mod b \\iff a - (a \\mid b) \\times b $"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "adc3fb84",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:35:28.639789Z",
     "start_time": "2023-08-07T12:35:28.621788Z"
    },
    "init_cell": true
   },
   "outputs": [],
   "source": [
    "def mod(a, b):\n",
    "  return a - (a//b)*b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "6bf27f7c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:35:37.664169Z",
     "start_time": "2023-08-07T12:35:37.657170Z"
    },
    "scrolled": false,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(41%14 == mod(41,14))\n",
    "print(14%41 == mod(14,41))\n",
    "print(-32%9 == mod(-32,9))\n",
    "print(32%-9 == mod(32,-9))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55da0c0a",
   "metadata": {},
   "source": [
    "补充资料：注意 `%` 与 `math.fmod()` 的区别，详见：[Modulo operation](https://en.wikipedia.org/wiki/Modulo_operation)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71702db7",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 类型影响语义 Types Affect Semantics\n",
    "\n",
    "运算符的运作方式会受到**运算数据的类型**的影响"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "a2ec28b2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:40:41.152378Z",
     "start_time": "2023-08-07T12:40:41.125382Z"
    },
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n",
      "p2sp2sp2s\n",
      "5\n",
      "Datawhale\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "unsupported operand type(s) for +: 'int' and 'str'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn [41], line 5\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;241m3\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m2\u001b[39m)\n\u001b[0;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mData\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwhale\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m----> 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mp2s\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m)\n",
      "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'str'"
     ]
    }
   ],
   "source": [
    "print(3 * 2)\n",
    "print(3 * \"p2s\")\n",
    "print(3 + 2)\n",
    "print(\"Data\" + \"whale\")\n",
    "print(3 + \"p2s\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e14a29d",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 运算符优先级 Operator Order\n",
    "### 优先顺序与结合律 Precedence and Associativity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "cfdc8808",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:42:55.775842Z",
     "start_time": "2023-08-07T12:42:55.758839Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"1300\"\n",
       "            height=\"600\"\n",
       "            src=\"https://docs.python.org/zh-cn/3.9/reference/expressions.html#operator-precedence\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x20ce54fcc40>"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import IFrame\n",
    "IFrame('https://docs.python.org/zh-cn/3.9/reference/expressions.html#operator-precedence', width=1300, height=600)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68caa046",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "优先顺序 Precedence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "d3d5896f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:44:30.857216Z",
     "start_time": "2023-08-07T12:44:30.848215Z"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "14\n",
      "6\n",
      "32\n"
     ]
    }
   ],
   "source": [
    "print(2+3*4)  # 14（不是 20）\n",
    "print(5+4%3)  # 6（不是 0）\n",
    "print(2**3*4) # 32（不是 4096）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46d15034",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "结合律 Associativity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8c886b3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-11-19T11:33:19.307569Z",
     "start_time": "2022-11-19T11:33:19.302569Z"
    }
   },
   "outputs": [],
   "source": [
    "print(5-4-3)   # -2（不是 4）\n",
    "print(4**3**2) # 262144（不是 4096）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5dd0be24",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-10-11T11:31:13.029948Z",
     "start_time": "2022-10-11T11:31:13.023949Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "浮点数误差"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e4d16936",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:47:37.341815Z",
     "start_time": "2023-08-07T12:47:37.325300Z"
    },
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "0.30000000000000004\n",
      "5.551115123125783e-17\n"
     ]
    }
   ],
   "source": [
    "print(0.1 + 0.1 == 0.2)        # True\n",
    "print(0.1 + 0.1 + 0.1 == 0.3)  # False!\n",
    "print(0.1 + 0.1 + 0.1)         # Why?\n",
    "print((0.1 + 0.1 + 0.1) - 0.3) # 特别小，但不是 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac3f81f0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-10-11T11:31:45.597776Z",
     "start_time": "2022-10-11T11:31:45.592776Z"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 短路求值 Short-Circuit Evaluation\n",
    "\n",
    "逻辑运算参照表\n",
    "\n",
    "| X     | Y     | X and Y | X or Y | not X | not Y |\n",
    "| ----- | ----- | ------- | ------ | ----- | ----- |\n",
    "| True  | True  | True    | True   | False | False |\n",
    "| True  | False | False   | True   | False | True  |\n",
    "| False | False | False   | False  | True  | True  |\n",
    "| False | True  | False   | True   | True  | False |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da068c77",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "我们先来定义一些函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "aeb3657f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:52:23.942600Z",
     "start_time": "2023-08-07T12:52:23.934600Z"
    },
    "init_cell": true
   },
   "outputs": [],
   "source": [
    "def yes():\n",
    "    return True\n",
    "\n",
    "def no():\n",
    "    return False\n",
    "\n",
    "def crash():\n",
    "    return 1/0 # 会崩溃！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "4c58c158",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T12:59:03.283075Z",
     "start_time": "2023-08-07T12:59:03.257075Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "division by zero",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mZeroDivisionError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn [47], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;28mprint\u001b[39m(no() \u001b[38;5;129;01mand\u001b[39;00m crash()) \u001b[38;5;66;03m# 成功运行！\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m (yes() \u001b[38;5;129;01mand\u001b[39;00m \u001b[43mcrash\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m)\n",
      "Cell \u001b[1;32mIn [45], line 8\u001b[0m, in \u001b[0;36mcrash\u001b[1;34m()\u001b[0m\n\u001b[0;32m      7\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcrash\u001b[39m():\n\u001b[1;32m----> 8\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;241;43m1\u001b[39;49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m\n",
      "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero"
     ]
    }
   ],
   "source": [
    "print(no() and crash()) # 成功运行！\n",
    "print(crash() and no()) # 崩溃了！\n",
    "print (yes() and crash()) # 因为上一行崩溃了，所以这行不会被运行，就是运行也会因为短路求值崩溃"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1f47344",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "我们换成 `or`，再来试试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "5a18c4bc",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:01:10.071755Z",
     "start_time": "2023-08-07T13:01:10.043754Z"
    },
    "scrolled": false,
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "division by zero",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mZeroDivisionError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn [50], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;28mprint\u001b[39m(yes() \u001b[38;5;129;01mor\u001b[39;00m crash()) \u001b[38;5;66;03m# 成功运行\u001b[39;00m\n\u001b[0;32m      2\u001b[0m \u001b[38;5;66;03m# print(crash() or yes()) # 崩溃了\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(no() \u001b[38;5;129;01mor\u001b[39;00m \u001b[43mcrash\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m)\n",
      "Cell \u001b[1;32mIn [45], line 8\u001b[0m, in \u001b[0;36mcrash\u001b[1;34m()\u001b[0m\n\u001b[0;32m      7\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcrash\u001b[39m():\n\u001b[1;32m----> 8\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;241;43m1\u001b[39;49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m\n",
      "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero"
     ]
    }
   ],
   "source": [
    "print(yes() or crash()) # 成功运行\n",
    "# print(crash() or yes()) # 崩溃了\n",
    "print(no() or crash())  # 因为上一行崩溃了，所以这行不会被运行，就是运行也会因为短路求值崩溃"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "baed9c84",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "再来个例子，我们也先定义些函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "daaf159f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:01:24.166067Z",
     "start_time": "2023-08-07T13:01:24.160079Z"
    },
    "init_cell": true,
    "scrolled": true,
    "slideshow": {
     "slide_type": ""
    }
   },
   "outputs": [],
   "source": [
    "def isPositive(n):\n",
    "    result = (n > 0)\n",
    "    print(n, \"是不是正数？\", result)\n",
    "    return result\n",
    "\n",
    "def isEven(n):\n",
    "    result = (n % 2 == 0)\n",
    "    print(n, \"是不是偶数？\", result)\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "a2df554e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:15:22.917930Z",
     "start_time": "2023-08-07T13:15:22.911929Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-4 是不是偶数？ True\n",
      "-4 是不是正数？ False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(isEven(-4) and isPositive(-4)) # 调用了两个函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "07ed7e7e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:03:51.701974Z",
     "start_time": "2023-08-07T13:03:51.698977Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-3 是不是偶数？ False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(isEven(-3) and isPositive(-3)) # 只调用了一个函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d20265e6",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# `type()` vs `isinstance()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "3ceee581",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:06:13.695009Z",
     "start_time": "2023-08-07T13:06:13.676010Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(type(\"p2s\") == str)\n",
    "print(isinstance(\"p2s\", str))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea4deefa",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "任务：编写代码，判断 `x` 是不是数字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "366d2b0c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:07:43.000038Z",
     "start_time": "2023-08-07T13:07:42.984035Z"
    },
    "init_cell": true
   },
   "outputs": [],
   "source": [
    "def isNumber(x):\n",
    "    return ((type(x) == int) or\n",
    "            (type(x) == float)) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "330f5924",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "你能确保它能够判断**所有数字**吗？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "89bc1993",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:08:25.043641Z",
     "start_time": "2023-08-07T13:08:25.024642Z"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True True False False\n"
     ]
    }
   ],
   "source": [
    "print(isNumber(1), isNumber(1.1), isNumber(1+2j), isNumber(\"p2s\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5cd8468",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "- `isinstance()` 比 `type()` 更具有 `稳健性（Robustness）` \n",
    "- 这种做法更加符合 `面向对象编程` 中 `继承（inheritance）` 的思想"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "15a5a05d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:09:50.766079Z",
     "start_time": "2023-08-07T13:09:50.763076Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "import numbers\n",
    "def isNumber(x):\n",
    "    return isinstance(x, numbers.Number) # 可以应对任何类型的数字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "42df3783",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-08-07T13:09:52.392324Z",
     "start_time": "2023-08-07T13:09:52.384325Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True True True False\n"
     ]
    }
   ],
   "source": [
    "print(isNumber(1), isNumber(1.1), isNumber(1+2j), isNumber(\"p2s\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cef85c96",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 总结\n",
    "\n",
    "- Python 的类型系统很丰富，可以**使用 `type()` 查看对应的类型**\n",
    "- 常数类型的**值是不可修改的**\n",
    "- 除法操作**默认是浮点数除法**，整除操作需要使用 `//`\n",
    "- 运算符之间有运算优先级，运算符作用于不同对象之间的效果是不同的\n",
    "- 在进行逻辑判断时，会使用**短路求值**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da42457b",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Thank You ;-)\n",
    "Datawhale 聪明办法学 Python 教学团队出品\n",
    "\n",
    "## 关注我们\n",
    "Datawhale 是一个专注 AI 领域的开源组织，以“for the learner，和学习者一起成长”为愿景，构建对学习者最有价值的开源学习社区。关注我们，一起学习成长。\n",
    "<div align=center><img src=\"../resources/datawhale_wechat_qrcode.jpeg\" width = \"250\" height = \"270\"></div>"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "rise": {
   "overlay": "<div class='my-top-right'><img height=40px src='../resources/datawhale_logo.png'/></div><div class='my-top-left'></div>"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "大纲 Outline",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
